package com.ktjiaoyu.crm.controller;

import com.ktjiaoyu.crm.config.shiro.MyShiroRealm;
import com.ktjiaoyu.crm.pojo.Right;
import com.ktjiaoyu.crm.pojo.User;
import com.ktjiaoyu.crm.redis.RedisTemplateUtil;
import com.ktjiaoyu.crm.service.RightService;
import com.ktjiaoyu.crm.service.UserService;
import com.ktjiaoyu.crm.util.PasswordUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Set;

@Slf4j
@Controller
public class LoginController {

    @Autowired
    private UserService userService;

    @Autowired
    private RightService rightService;

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    private String SHIRO_LOGIN_COUNT = "shiro_login_count"; //登录次数计数

    @RequestMapping(value = "/toLogin")
    public String toLogin(){

        return "login";
    }

    @RequestMapping(value = "/toMain")
    public String toMain(){

        return "main";
    }

    @RequestMapping(value = "/403")
    public String unAuthorized(){

        return "403";
    }

    @PostMapping(value = "login")
    public String login(User user, HttpSession session, Model model){
        try {
            log.info("{}用户进入认证方法.............",user.getUsrName());
            //调用Shiro进行用户认证
            //封装token，对明文密码进行加密
            //user.setUsrPassword(PasswordUtils.encryptPassword(user.getUsrPassword()));
            //构建用户token
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsrName(),user.getUsrPassword());
            //获取Subject
            Subject subject = SecurityUtils.getSubject();
            //登录
            subject.login(token);
            //获取返回的用户信息，如果不为空，说明登录成功，跳转到主页
            User resultUser = (User) subject.getPrincipal();
            //查询当前登录用户的菜单
            List<Right> rightsList = rightService.getRightsByRoleId(resultUser.getRole().getRoleId());
            //将用户信息存入session
            session.setAttribute("loginUser",resultUser);
            session.setAttribute("rights",rightsList);
            //清除登录次数
            redisTemplateUtil.del(SHIRO_LOGIN_COUNT+resultUser.getUsrName());
            //清空当前用户权限缓存
            RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
            MyShiroRealm realm = (MyShiroRealm) rsm.getRealms().iterator().next();
            realm.clearMyCachedAuthorizationInfo();


            log.info("{}用户认证完成.............",user.getUsrName());
            return "redirect:/toMain";
        }  catch (UnknownAccountException | IncorrectCredentialsException e){
            log.error("异常原因："+user.getUsrName()+"用户名或密码错误，登录失败！");
            model.addAttribute("msg","用户名或密码错误，登录失败！ ");
            return "forward:/toLogin";
        } catch (LockedAccountException e){
            log.error("异常原因："+user.getUsrName()+"用户被禁用，登录失败！");
            model.addAttribute("msg","用户被禁用，登录失败！ ");
            return "forward:/toLogin";
        } catch (DisabledAccountException e){
            log.error("异常原因："+user.getUsrName()+"账号登录失败次数超过5次，已被锁定！");
            model.addAttribute("msg","账号登录失败次数超过5次，已被锁定！ ");
            return "forward:/toLogin";
        } catch (AuthenticationException e){
            log.error("异常原因："+user.getUsrName()+"认证异常，登录失败！");
            model.addAttribute("msg","认证异常，登录失败！ ");
            return "forward:/toLogin";
        } catch (Exception e) {
            log.error("出现其他异常！异常原因：{}",e.getLocalizedMessage(),e);
            model.addAttribute("msg","出现其他异常！");
            e.printStackTrace();
            return "forward:/toLogin";
        }
    }

    /**
     * 注销
     * @param session
     * @return
     */
    @RequestMapping(value = "/logout")
    public String logout(HttpSession session){
        session.removeAttribute("loginUser");   //删除session中保存的用户信息
        return "login";
    }

}
